import { Message } from './libs/Message';
import { Channel } from './libs/Channel';
import { Cmd }     from './libs/Cmd';

/**
 * WebSocket消息格式
 */
class WebSocketMessage implements Message {

    /**
     * uuid
     * @type {string}
     */
    uuid:string;

    /**
     * 频道
     * @type {Channel}
     */
    channel:Channel;

    /**
     * 命令
     * @type {Cmd}
     */
    cmd:Cmd;

    /**
     * 传输数据
     * @type {any}
     */
    data:any;

    /**
     * 利用信息结构构造
     * @param {string} uuid
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     */
    private constructor(channel:Message)

    /**
     * 构造
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     * @private
     */
    private constructor(channel:Channel, cmd:Cmd, data:any)

    /**
     * 构造
     * @param {string} uuid
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     */
    private constructor(channel:any, cmd ?:any, data?:any) {
        let uuid = WebSocketMessage.uuidGenerate();
        if (typeof (channel as Message).channel === 'undefined') {
            this.uuid    = uuid;
            this.channel = channel;
            this.cmd     = cmd;
            this.data    = JSON.stringify(data);
        } else {
            this.uuid    = channel.uuid || uuid;
            this.channel = channel.channel;
            this.cmd     = channel.cmd;
            this.data    = JSON.stringify(channel.data);
        }
    }

    /**
     * 利用个信息结构获取实例
     * @param {Message} channel
     * @return {String}
     */
    static of(channel:Message):WebSocketMessage

    /**
     * 获取实例
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     * @return {String}
     */
    static of(channel:Channel, cmd:Cmd, data:any):WebSocketMessage

    /**
     * 获取实例
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     * @return {String}
     */
    static of(channel:any, cmd?:any, data?:any):WebSocketMessage {
        return new WebSocketMessage(channel, cmd, data);
    }


    /**
     * 利用个信息结构获取实例Json
     * @param {Message} channel
     * @return {String}
     */
    static stringifyOf(channel:Message):String

    /**
     * 获取实例Json
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     * @return {String}
     */
    static stringifyOf(channel:Channel, cmd:Cmd, data:any):String

    /**
     * 获取实例Json
     * @param {Channel} channel
     * @param {Cmd} cmd
     * @param data
     * @return {String}
     */
    static stringifyOf(channel:any, cmd?:any, data?:any):String {
        return JSON.stringify(this.of(channel, cmd, data));
    }

    /**
     * 生成UUID
     * @return {string}
     * @private
     */
    private static uuidGenerate():string {
        let d           = new Date().getTime();
        let uuid:string = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
            let r = (d + Math.random() * 16) % 16 | 0;
            d     = Math.floor(d / 16);
            return (c == 'x' ? r : (r & 0x7) | 0x8).toString(16);
        });
        return uuid;
    }
}

/**
 * 导出
 */
export default WebSocketMessage;

/**
 * 导出
 */
export { Cmd, Message, Channel };
